/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/memory
// Copyright( c) 2013.  All Rights Reserved
//
// File:		AESubjectI.h
// Author:		Gianluca Belardelli
// Date:		09/04/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AESUBJECTI_H_
#define _AESUBJECTI_H_

////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///   The <c>ISubject</c> interface supplies loosely coupling systems with dependency
///       It facilitates a lazy behaviour where by systems only need to react to a change
///		  and facilitates dependent callback threading.      
/// </summary>
/// <remarks>
///    Related interfaces: \n IObserver\n IChangeManager       
/// </remarks>
/// <remarks>
///    This interface follows the pattern commonly know as the Observer
///	   pattern, the Publish/Subscribe pattern, or the Dependents pattern. 
/// </remarks>
/// <remarks>
///    The Observer pattern is documented in "Design Patterns," written by
///	   Erich Gamma et. al., published by Addison-Wesley in 1995.          
/// </remarks>
/////////////////////////////////////////////////////////////////////////////////////////////////
class AESubjectI
{
// Methods
public:
    // All interfaces must have virtual destructors
    virtual ~AESubjectI ( void ) {}

    /// <summary>
    ///  Associates the provided IObserver with the given ISubject aspects of interest.
    /// </summary>
    /// <remarks>
    ///  This method is typically called from @e ChangeManager::Register()
    ///  or the IObserver, if used without a ChangeManager.             
    ///  </remarks>
    /// <param name="pInObserver"> A pointer to the IObserver.</param>
    /// <param name="uInIntrestBits"> The aspects of interest that changed as defined by the supplied
    ///				ISubject's published interest bits.</param>
    /// <param name="uID"> ID assigned by pInObserver to this subject.</param>
    /// <param name="shiftBits">Used for components supporting multiply inherited interfaces each
    ///				with subject interfaces.</param>
    /// <returns>One of the following Error codes:
    ///     Error::Success
    ///			No error.
    ///     Error::InvalidAddress 
    ///			pInObserver and/or pInSubject was NULL.
    ///     Error::OutOfMemory                                   
    ///			Not enough memory is available to resolve the change.
    ///</returns>
    virtual AEUINT32 Attach( AEObserverI *lpInObserver, AEUINT32 uiInIntrestBits, AEUINT32 uiID, AEUINT32 uiShiftBits = 0 ) = 0;

    /// <summary>
    ///  Disassociates the provided Observer with the Subject
    /// </summary>
    /// <remarks>
    ///  This method is typically called from @e ChangeManager::Register()
    ///  or the IObserver, if used without a ChangeManager.             
    ///  </remarks>
    /// <param name="pInObserver"> A pointer to the IObserver that should be disassociated.</param>
    /// <returns>One of the following Error codes:
    ///     Error::Success
    ///			No error.
    ///     Error::InvalidAddress 
    ///			pInObserver and/or pInSubject was NULL.
    ///</returns>
    virtual AEUINT32 Detach( AEObserverI *lpInObserver ) = 0;

    virtual AEUINT32 UpdateInterestBits( AEObserverI *lpInObserver, AEUINT32 uiInIntrestBitsMask ) = 0;

    /// <summary>
    ///  Returns the ID assigned by pObserver to this subject
    /// </summary>
    virtual AEUINT32 GetID ( AEObserverI *lpObserver ) const = 0;

    /// <summary>
    ///  Publishes to attached Observers and ChanageManager that changes have occurred.
    /// </summary>
    /// <remarks>
    ///  This method is typically called from @e ChangeManager::Register()
    ///  or the IObserver, if used without a ChangeManager.             
    ///  </remarks>
    /// <param name="uInChangedBits"> TThe u32 bit field that describes the conceptual change with 
    ///				 respect to the published interests.
    /// </param>
    /// <returns>One of the following Error codes:
    ///     Error::Success
    ///			No error.
    ///     Error::InvalidAddress 
    ///			pInObserver and/or pInSubject was NULL.
    ///</returns>
	virtual void PostChanges( AEUINT32 uiInChangedMask ) = 0;

    /// <summary>
    ///   Identifies the system changes that this subject could possibly make.
    /// </summary>
    /// <returns>A bitmask of the possible system changes.</returns>
    virtual AEUINT32 GetPotentialSystemChangesMask( void ) = 0;

    /// <summary>
    ///  Forces the Destruction 
    /// </summary>
    /// <remarks>
    ///	            
    ///  </remarks>
    /// <returns>One of the following Error codes:
    ///     Error::Success
    ///			No error.
    ///     Error::InvalidAddress 
    ///			pInObserver and/or pInSubject was NULL.
    ///</returns>
    virtual void PreDestruct( void ) = 0;
};

#endif _AESUBJECTI_H_